//
//  KyoTransitioningDelegate.swift
//  test1
//
//  Created by Kyo on 2019/9/25.
//  Copyright © 2019 Kyo. All rights reserved.
//

import UIKit

// MARK: -------------------------
// MARK: Const/Enum/Struct

extension KyoTransitioning {
    
    /** 常量  */
    public struct Const {
        /** 默认动画时间（没设置时间时使用） */
        public static let defaultDuartion: Float = 0.4
        /** 默认关闭手势 */
        public static let defaultEnableInteractive: Bool = false
    }
    
    /** 通知名 */
    public struct NotificationName {
        public static let pushFinish = Notification.Name("KyoTransitioningPushFinish")
        public static let popFinish = Notification.Name("KyoTransitioningPopFinish")
    }
    
    /** 通知UseInfo key */
    public struct NotificationKey {
        public static let fromController = "fromController"
        public static let toController = "toController"
    }
    
    /** push/pop 操作数据model */
    public struct AnimationOperateModel {
        /** 动画控制的controller  */
        public weak var controller: UIViewController?
        /** push到的控制器（操作类型为push才需要设置） */
        public weak var pushToViewController: UIViewController?
        /** 操作类型 push或pop */
        public var operation: KyoTransitioningAnimation.Operation?
        /**  动画类型 */
        public var animationType: KyoTransitioningAnimation.AnimationType?
        /** 动画时间 需要默认时间则不传 */
        public var duration: Float? = Const.defaultDuartion
        /** 动画实例需要的参数 key对应属性名，value对应值 （动画类型为scaleToFull才需要设置） */
        public var animatorParams: [String: Any]? = nil
        /** 是否开启手势 */
        public var isEnableInteractive: Bool = Const.defaultEnableInteractive
        /** 动画实例 */
        public var transition: KyoTransitioningAnimation?
        /** 交互手势实例 */
        public var interactive: KyoTransitioningInteractive?
        
        public init(controller: UIViewController? = nil,
                    pushToController: UIViewController? = nil,
                    operation: KyoTransitioningAnimation.Operation? = nil,
                    animationType: KyoTransitioningAnimation.AnimationType? = nil,
                    duration: Float? = Const.defaultDuartion,
                    animatorParams: [String: Any]? = nil,
                    isEnableInteractive: Bool = Const.defaultEnableInteractive) {
            self.controller = controller
            self.pushToViewController = pushToController
            self.operation = operation
            self.animationType = animationType
            self.duration = duration
            self.animatorParams = animatorParams
            self.isEnableInteractive = isEnableInteractive
            self.transition = KyoTransitioningAnimation.generate(type: self.animationType,
                                                                 operation: operation,
                                                                 duration: self.duration ?? Const.defaultDuartion,
                                                                 animatorParams: self.animatorParams)
            self.interactive = KyoTransitioningInteractive.generate(controller: self.controller,
                                                                    pushToController: self.pushToViewController,
                                                                    operation: operation ?? .pop,
                                                                    type: self.animationType)
        }
    }
    
}

@objc public class KyoTransitioning: NSObject {
    
    // MARK: -------------------------
    // MARK: Propertys
    
    public var animationOperates: [AnimationOperateModel]?
    
    // MARK: -------------------------
    // MARK: CycLife
    
    /** 初始化，传入动画需要的数据 */
    public init(animationOperates: [AnimationOperateModel]?) {
        super.init()
        self.animationOperates = animationOperates
        self.animationOperates?.enumerated().forEach {$0.element.controller?.navigationController?.delegate = self}
    }
    
    /** oc调用 初始化 */
    @objc public convenience init(animationOperatesKeyValues: [[String: Any]]?) {
        let animationOperates: [AnimationOperateModel]? = animationOperatesKeyValues?.map { (keyValues) -> AnimationOperateModel in
            var animatorParams: [String: Any]? = keyValues["animatorParams"] as? [String: Any]
            if let catransform3DValue = animatorParams?[KyoTransitioningScale.Const.keyForTransform] as? NSValue {
                animatorParams?[KyoTransitioningScale.Const.keyForTransform] = catransform3DValue.caTransform3DValue
            }
            return AnimationOperateModel(controller: keyValues["controller"] as? UIViewController,
                                         pushToController: keyValues["pushToController"] as? UIViewController,
                                         operation: KyoTransitioningAnimation.Operation(rawValue: (keyValues["operation"] as? NSNumber)?.intValue ?? 0),
                                         animationType: KyoTransitioningAnimation.AnimationType(rawValue: (keyValues["animationType"] as? NSNumber)?.intValue ?? 0),
                                         duration: (keyValues["duration"] as? NSNumber)?.floatValue,
                                         animatorParams: keyValues["animatorParams"] as? [String: Any],
                                         isEnableInteractive: (keyValues["animationType"] as? NSNumber)?.boolValue ?? false)
        }
        self.init(animationOperates: animationOperates)
    }
    
    deinit {
        self.animationOperates?.enumerated().forEach {
            if $0.element.controller?.navigationController?.delegate?.isEqual(self) ?? false {
                $0.element.controller?.navigationController?.delegate = nil
            }
        }
    }
    
    // MARK: -------------------------
    // MARK: Events
    
    // MARK: -------------------------
    // MARK: Methods
    
}

extension KyoTransitioning: UINavigationControllerDelegate {
    
    public func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return self.animationOperates?.first{$0.operation == operation}?.transition
    }
    
    public func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
        guard let animationOperate = (self.animationOperates?.first{$0.transition?.isEqual(animationController) ?? false}) else {return nil}
        guard animationOperate.interactive?.isInGesture() ?? false else {return nil}
        switch animationOperate.operation {
        case .pop:
            return animationOperate.isEnableInteractive ? animationOperate.interactive?.interactive : nil
        case .push:
            return animationOperate.isEnableInteractive ? animationOperate.interactive?.interactive : nil
        default: return nil
        }
    }
    
}
